import docker
from docker.types import Resources

# 在Docker Swarm中创建一个Jupyter镜像服务
# docker_api_url：集群中主控节点的Docker服务URL。例如：192.168.0.33:5001
# service_name：待创建的服务名称，该名称必须是唯一的。例如：lab-jerry
# image_name：待创建的服务所使用镜像全名称，该镜像是应该在私有注册服务其中存在的。例如：192.168.0.33:5000/kp-base-notebook:1.0
# mount_host_path：宿主机中保存与该用户相关的容器实例数据的目录。例如：/data/jerry
# docker_workspace_path：Jupyter镜像中的用户工作目录。默认是/home/jovyan/work
# docker_port：Jupyter镜像中网站的默认监听端口。默认是8888
def create_service(docker_api_url, service_name, image_name, mount_host_path, docker_workspace_path='/home/jovyan/work', docker_port=8888):
    docker_client = docker.DockerClient(base_url=docker_api_url)
    # 指定端口映射
    endpoint_spec = {'Mode':'vip', 'Ports':[{'Protocal':'tcp', 'PublishMode':'ingress', 'TargetPort':docker_port}]}
    # 定义数据目录映射
    mount = '{}:{}:rw'.format(mount_host_path, docker_workspace_path)
    # 设置最大占用CPU限制为：2核(10^9为1核)
    # 设置最大占用内存限制为：1GB(2**30字节为1GB)
    resources = Resources(cpu_limit=2*10**9, mem_limit=2**30)
    try:
        # 创建Service
        service = docker_client.services.create(
            image = image_name,
            endpoint_spec = endpoint_spec,
            mounts = [mount], 
            resources = resources,
            name = service_name)
        return True
    except docker.errors.APIError as ex:
        print(ex)
        return False
    finally:
        docker_client.close()

# 请将docker_api_url修改为自己创建的Docker Swarm集群主控节点的Docker远程服务URL
docker_api_url = '192.168.0.33:5001' 
# 请将image_name修改为自己创建的私有Registry镜像全名称
image_name = '192.168.0.33:5000/kp-base-notebook:1.0'
client = docker.DockerClient(base_url=docker_api_url)
service_name = 'lab-jerry'
mount_host_path = '/data/jerry'
result = create_service(docker_api_url, service_name, image_name, mount_host_path)
if result:
    print("service ", service_name, " created successfully.")
